home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / text / tex / tgrind.lha / TGrind / tfontedpr.c < prev    next >
C/C++ Source or Header  |  1993-01-04  |  17KB  |  673 lines

  1. #ifndef lint
  2. static char rcsid[] =
  3.     "$Header: tfontedpr.c,v 1.3 88/07/05 05:15:52 van Exp $ (LBL)";
  4. #endif
  5.  
  6. /*
  7.  * tfontedpr - general purpose "pretty printer" for use with TeX.
  8.  *
  9.  * Copyright (C) 1985 by Van Jacobson, Lawrence Berkeley Laboratory. This
  10.  * program may be freely used and copied but may not be sold without the
  11.  * author's written permission.  This notice must remain in any copy or
  12.  * derivative.
  13.  *
  14.  * This program is used as part of the "tgrind" shell script.  It converts
  15.  * program source file(s) to TeX input files.
  16.  *
  17.  * This program is an adaptation of "vfontedpr" v4.2 (12/11/84) from the 4.2bsd
  18.  * Unix distribution.  Vfontedpr was written by Dave Presotto (based on an
  19.  * earlier program of the same name written by Bill Joy).
  20.  *
  21.  * I would welcome comments, enhancements, bug fixes, etc.
  22.  *    van@lbl-csam.arpa    (from arpanet, milnet, csnet, etc.)
  23.  *    ..!ucbvax!lbl-csam!van    (from Usenet/UUCP)
  24.  */
  25.  
  26. /**
  27.  ** Amiga port by Kari Sutela, University of Turku.
  28.  **/
  29.  
  30. #include <ctype.h>
  31. #include <stdio.h>
  32. #include <sys/types.h>
  33. #include <stat.h>
  34. #include <string.h>
  35. #include <stdlib.h>
  36. #include <time.h>
  37.  
  38. #include "regexp_protos.h"
  39. #include "vgrindefs_protos.h"
  40. void putScp(char * );
  41. void putKcp(char * , char * , int );
  42. int width(char * , char * );
  43. void putstr(char * );
  44. int isproc(char * );
  45. int iskw(char * );
  46.  
  47. #ifndef boolean
  48. #define boolean int
  49. #define TRUE 1
  50. #define FALSE 0
  51. #endif
  52. #define NIL 0
  53. #define STANDARD 0
  54. #define ALTERNATE 1
  55.  
  56. #define STRLEN 10        /* length of strings introducing things */
  57. #define PNAMELEN 80        /* length of a function/procedure name */
  58. #define PSMAX 20        /* size of procedure name stacking */
  59.  
  60. /* regular expression routines */
  61.  
  62. char *expmatch ();        /* match a string to an expression */
  63. char *convexp ();        /* convert expression to internal form */
  64. char *tgetstr ();
  65. boolean isproc ();
  66. char *ctime ();
  67.  
  68. /*
  69.  * The state variables
  70.  */
  71. boolean incomm;            /* in a comment of the primary type */
  72. boolean instr;            /* in a string constant */
  73. boolean inchr;            /* in a string constant */
  74. boolean nokeyw;            /* no keywords being flagged */
  75. boolean filtermode;        /* our output won't go straight to tex */
  76. boolean prccont;        /* continue last procedure */
  77. int comtype;            /* type of comment */
  78. int psptr;            /* the stack index of the current procedure */
  79. char pstack[PSMAX][PNAMELEN+1];    /* the procedure name stack */
  80. int plstack[PSMAX];        /* the procedure nesting level stack */
  81. int blklevel;            /* current nesting level */
  82. #ifndef DEFSFILE
  83. char *defsfile = "tex:inputs/tgrindefs";    /* name of language definitions file */
  84. #else
  85. char *defsfile = DEFSFILE;
  86. #endif
  87. char pname[BUFSIZ + 1];
  88.  
  89. /*
  90.  * language specific globals
  91.  */
  92. char *language = "c";        /* the language indicator */
  93. char *l_keywds[BUFSIZ / 2];    /* keyword table address */
  94. char *l_prcbeg;            /* regular expr for procedure begin */
  95. char *l_combeg;            /* string introducing a comment */
  96. char *l_comend;            /* string ending a comment */
  97. char *l_acmbeg;            /* string introducing a comment */
  98. char *l_acmend;            /* string ending a comment */
  99. char *l_blkbeg;            /* string begining of a block */
  100. char *l_blkend;            /* string ending a block */
  101. char *l_strbeg;            /* delimiter for string constant */
  102. char *l_strend;            /* delimiter for string constant */
  103. char *l_chrbeg;            /* delimiter for character constant */
  104. char *l_chrend;            /* delimiter for character constant */
  105. char l_escape;            /* character used to escape characters */
  106. boolean l_toplex;        /* procedures only defined at top lex level */
  107. boolean l_onecase;        /* upper & lower case equivalent */
  108.  
  109. /*
  110.  * global variables also used by expmatch
  111.  */
  112. extern boolean _escaped;    /* if last character was an escape */
  113. extern char *_start;        /* start of the current string */
  114.  
  115. int (*re_strncmp) (char *, char *, size_t);        /* function to do string compares */
  116.  
  117. /*
  118.  * The following table converts ASCII characters to a printed representation,
  119.  * taking care of all the TeX quoting.  N.B.: all single-character strings
  120.  * are assumed to be equivalent to the character for that index (i.e.,
  121.  * printtab['c'] can't be "f"). (This is purely for efficiency hacking.)
  122.  */
  123. char *printtab[128] = {
  124.     "\0x", "\\^A", "\\^B", "\\^C", "\\^D", "\\^E", "\\^F", "\\^G",
  125.     "\\^H", "\t", "}}\n", "\\^K", "\0x", "\\^M", "\\^N", "\\^O",
  126.     "\\^P", "\\^Q", "\\^R", "\\^S", "\\^T", "\\^U", "\\^V", "\\^W",
  127.     "\\^X", "\\^Y", "\\^Z", "\\^[", "\\^\\!", "\\^]", "\\^\\^", "\\^_",
  128.     " ", "!", "\\\"", "\\#", "\\$", "\\%", "\\&", "\\'",
  129.     "(", ")", "\\*", "+", ",", "\\-", ".", "\\/",
  130.     "0", "1", "2", "3", "4", "5", "6", "7",
  131.     "8", "9", ":", ";", "\\<", "=", "\\>", "?",
  132.     "@", "A", "B", "C", "D", "E", "F", "G",
  133.     "H", "I", "J", "K", "L", "M", "N", "O",
  134.     "P", "Q", "R", "S", "T", "U", "V", "W",
  135.     "X", "Y", "Z", "[", "\\!", "]", "\\^", "\\_",
  136.     "`", "a", "b", "c", "d", "e", "f", "g",
  137.     "h", "i", "j", "k", "l", "m", "n", "o",
  138.     "p", "q", "r", "s", "t", "u", "v", "w",
  139.     "x", "y", "z", "\\{", "\\|", "\\}", "\\~", "\\^?",
  140. };
  141.  
  142. /*
  143.  * The following table tells what characters a legal in identifiers
  144.  * and keywords.  We build it from the list of keywords and the
  145.  * id= string.
  146.  */
  147. static char *IDChar[256];
  148.  
  149. #define isIDchr(c) (IDChar[(unsigned)(c)])
  150.  
  151. /*
  152.  * Output a character, with translation.  Avoid side effects with this macro!
  153.  */
  154. #define outchar(c) ((c >= 0 && c < 128) ? \
  155.     (printtab[c][1] ? printf("%s", printtab[c]) : putchar(c)) : \
  156.     putchar(c) )
  157.  
  158. /*
  159.  * Output a TeX command to tab to column "col" (see tgrindmac.tex for a
  160.  * partial explanation of the bizarre brace arrangement).
  161.  */
  162. #define tabto(col) printf("}\\Tab{%d}{", col);
  163.  
  164. int main (int argc, char *argv[])
  165. {
  166.     char *fname = "", *p;
  167.     struct stat stbuf;
  168.     char buf[BUFSIZ];
  169.     char strings[2 * BUFSIZ];
  170.     char defs[2 * BUFSIZ];
  171.     register char *cp;
  172.     register int i;
  173.     int newlang = 1;
  174.     int first = 1;
  175.  
  176.     while (--argc > 0) {
  177.         ++argv;
  178.         if (argv[0][0] == '-' && argv[0][1]) {
  179.             if (!strcmp (argv[0], "-h")) {
  180.                 if (argc == 1) {
  181.                     printf ("\\Head{}\n");
  182.                 }
  183.                 else {
  184.                     argc--, argv++;
  185.                     printf ("\\Head{");
  186.                     putstr (argv[0]);
  187.                     printf ("}\n");
  188.                 }
  189.             }
  190.             /* take input from the standard place */
  191.             else if (!strcmp (argv[0], "-")) {
  192.             }
  193.             /* we're operating as a filter */
  194.             else if (!strcmp (argv[0], "-f")) {
  195.                 filtermode++;
  196.             }
  197.             /* indicate no keywords */
  198.             else if (!strcmp (argv[0], "-n")) {
  199.                 nokeyw++;
  200.             }
  201.             /* specify the language */
  202.             else if (!strncmp (argv[0], "-l", 2)) {
  203.                 if (argv[0][2])
  204.                     language = argv[0] + 2;
  205.                 else {
  206.                     if (argc == 1) {
  207.                         fprintf (stderr,
  208.                          "language name must follow -l\n");
  209.                         exit (1);
  210.                     }
  211.                     argc--, argv++;
  212.                     language = argv[0];
  213.                 }
  214.                 newlang = 1;
  215.             }
  216.             /* specify the language description file */
  217.             else if (!strncmp (argv[0], "-d", 2)) {
  218.                 if (argv[0][2])
  219.                     defsfile = argv[0] + 2;
  220.                 else {
  221.                     if (argc == 1) {
  222.                         fprintf (stderr,
  223.                          "descr. file name must follow -d\n");
  224.                         exit (1);
  225.                     }
  226.                     argc--, argv++;
  227.                     defsfile = argv[0];
  228.                 }
  229.                 newlang = 1;
  230.             }
  231.             continue;
  232.         }
  233.         /* here to do another file */
  234.         if (argv[0][0] != '-') {
  235.             /* open the file for input */
  236.             if (freopen (argv[0], "r", stdin) == NULL) {
  237.                 perror (argv[0]);
  238.                 exit (1);
  239.             }
  240.             fname = argv[0];
  241.         }
  242.         if (first && ! filtermode) {
  243.             printf ("\\input tgrindmac\n");
  244.             first = 0;
  245.         }
  246.         /*
  247.          * get the  language definition from the defs file
  248.          */
  249.         if (newlang) {
  250.             i = tgetent (defs, language, defsfile);
  251.             if (i == 0) {
  252.                 fprintf (stderr, "no entry for language %s\n",
  253.                     language);
  254.                 exit (0);
  255.             } else if (i < 0) {
  256.                 fprintf (stderr,
  257.                     "cannot find tgrindefs file %s\n",
  258.                     defsfile);
  259.                 exit (0);
  260.             }
  261.             p = strings;
  262.             if (tgetstr ("kw", &p) == NIL)
  263.                 nokeyw = TRUE;
  264.             else {
  265.                 char **cpp;
  266.  
  267.                 cpp = l_keywds;
  268.                 cp = strings;
  269.                 while (i = *cp) {
  270.                     while (*cp == ' ' || *cp == '\t')
  271.                         /* was: *cp++ = NULL; */
  272.                         *cp++ = '\0';
  273.                     if (*cp)
  274.                         *cpp++ = cp;
  275.                     while ((i = *cp) && i != ' '
  276.                            && i != '\t') {
  277.                         ++cp;
  278.                         if (! IDChar[i])
  279.                             ++IDChar[i];
  280.                     }
  281.                 }
  282.                 *cpp = NIL;
  283.             }
  284.             p = buf;
  285.             if (tgetstr ("id", &p)) {
  286.                 for (cp = buf; i = *cp++;)
  287.                     if (! IDChar[i])
  288.                         ++IDChar[i];
  289.             }
  290.             else {
  291.                 /* default to C identifiers */
  292.                 for (i = 'A'; i <= 'Z'; ++i)
  293.                     ++IDChar[i];
  294.                 for (i = 'a'; i <= 'z'; ++i)
  295.                     ++IDChar[i];
  296.                 for (i = '0'; i <= '9'; ++i)
  297.                     ++IDChar[i];
  298.                 ++IDChar['_'];
  299.             }
  300.             p = buf;
  301.             l_prcbeg = convexp (tgetstr ("pb", &p));
  302.             p = buf;
  303.             l_combeg = convexp (tgetstr ("cb", &p));
  304.             p = buf;
  305.             l_comend = convexp (tgetstr ("ce", &p));
  306.             p = buf;
  307.             l_acmbeg = convexp (tgetstr ("ab", &p));
  308.             p = buf;
  309.             l_acmend = convexp (tgetstr ("ae", &p));
  310.             p = buf;
  311.             l_strbeg = convexp (tgetstr ("sb", &p));
  312.             p = buf;
  313.             l_strend = convexp (tgetstr ("se", &p));
  314.             p = buf;
  315.             l_blkbeg = convexp (tgetstr ("bb", &p));
  316.             p = buf;
  317.             l_blkend = convexp (tgetstr ("be", &p));
  318.             p = buf;
  319.             l_chrbeg = convexp (tgetstr ("lb", &p));
  320.             p = buf;
  321.             l_chrend = convexp (tgetstr ("le", &p));
  322.             l_escape = '\\';
  323.             l_onecase = tgetflag ("oc");
  324.             if (l_onecase)
  325.                 re_strncmp = lc_strncmp;
  326.             else
  327.                 re_strncmp = strncmp;
  328.             l_toplex = tgetflag ("tl");
  329.         }
  330.  
  331.         /* initialize the program */
  332.  
  333.         incomm = FALSE;
  334.         instr = FALSE;
  335.         inchr = FALSE;
  336.         _escaped = FALSE;
  337.         blklevel = 0;
  338.         for (psptr = 0; psptr < PSMAX; psptr++) {
  339.             /* was: pstack[psptr][0] = NULL; */
  340.             pstack[psptr][0] = '\0';
  341.             plstack[psptr] = 0;
  342.         }
  343.         psptr = -1;
  344. #ifdef OLDAMIGA
  345.         {
  346.             long ft;
  347.  
  348.             ft = getft(fname);
  349.             cp = ctime(&ft);
  350.         }
  351. #else
  352.         fstat (fileno (stdin), &stbuf);
  353.         /* Not needed: stat(fname,&stbuf); */
  354.         cp = ctime (&stbuf.st_mtime);
  355. #endif
  356.         cp[10] = '\0';
  357.         cp[16] = '\0';
  358.         cp[24] = '\0';
  359.         printf ("\\File{");
  360.         putstr (fname);
  361.         printf ("},{%s},{%s %s}\n", cp + 11, cp + 4, cp + 20);
  362.  
  363.         /*
  364.          * MAIN LOOP!!!
  365.          */
  366.         while (fgets (buf, sizeof buf, stdin) != NULL) {
  367.             cp = buf;
  368.             if (*cp == '\f') {
  369.                 printf ("\\NewPage\n");
  370.                 cp++;
  371.                 /* some people like ^Ls on their own line */
  372.                 if (*cp == '\n')
  373.                     continue;
  374.             }
  375.             prccont = FALSE;
  376.             printf ("\\L{\\LB{");
  377.             putScp (cp);
  378.             if (prccont && (psptr >= 0)) {
  379.                 printf ("\\ProcCont{");
  380.                 putstr (pstack[psptr]);
  381.                 printf ("}");
  382.             }
  383.         }
  384.     }
  385.     if (! filtermode)
  386.         printf ("\\vfill\\eject\\end\n");
  387.     exit (0);
  388. }
  389.  
  390. void putScp (char *os)
  391. {
  392.     register char *s = os;    /* pointer to unmatched string */
  393.     char *comptr;        /* start of a comment delimiter */
  394.     char *comendptr;    /* end of a comment delimiter */
  395.     char *acmptr;        /* start of an alt. comment delimiter */
  396.     char *acmendptr;    /* end of an alt. comment delimiter */
  397.     char *strptr;        /* start of a string delimiter */
  398.     char *strendptr;    /* end of a string delimiter */
  399.     char *chrptr;        /* start of a char. const delimiter */
  400.     char *chrendptr;    /* end of a char. const delimiter */
  401.     char *blksptr;        /* start of a lexical block start */
  402.     char *blksendptr;    /* end of a lexical block start */
  403.     char *blkeptr;        /* start of a lexical block end */
  404.     char *blkeendptr;    /* end of a lexical block end */
  405.  
  406.     _start = os;        /* remember the start for expmatch */
  407.     _escaped = FALSE;
  408.     if (nokeyw || incomm || instr)
  409.         goto skip;
  410.     if (isproc (s)) {
  411.         printf ("\\Proc{");
  412.         putstr (pname);
  413.         printf ("}");
  414.         if (!l_toplex && psptr < PSMAX - 1) {
  415.             ++psptr;
  416.             strncpy (pstack[psptr], pname, PNAMELEN);
  417.             /* was: pstack[psptr][PNAMELEN] = NULL; */
  418.             pstack[psptr][PNAMELEN] = '\0';
  419.             plstack[psptr] = blklevel;
  420.         }
  421.     }
  422. skip:
  423.     do {
  424.         /* check for string, comment, blockstart, etc */
  425.         if (!incomm && !instr && !inchr) {
  426.             blkeendptr = expmatch (s, l_blkend, &blkeptr, NIL);
  427.             blksendptr = expmatch (s, l_blkbeg, &blksptr, NIL);
  428.             comendptr = expmatch (s, l_combeg, &comptr, NIL);
  429.             acmendptr = expmatch (s, l_acmbeg, &acmptr, NIL);
  430.             strendptr = expmatch (s, l_strbeg, &strptr, NIL);
  431.             chrendptr = expmatch (s, l_chrbeg, &chrptr, NIL);
  432.  
  433.             /* start of a comment? */
  434.             if (comptr != NIL
  435.                 && (strptr == NIL || comptr < strptr)
  436.                 && (acmptr == NIL || comptr < acmptr)
  437.                 && (chrptr == NIL || comptr < chrptr)
  438.                 && (blksptr == NIL || comptr < blksptr)
  439.                 && (blkeptr == NIL || comptr < blkeptr)) {
  440.                 putKcp (s, comptr - 1, FALSE);
  441.                 printf ("\\C{}");
  442.                 s = comendptr;
  443.                 putKcp (comptr, comendptr - 1, FALSE);
  444.                 incomm = TRUE;
  445.                 comtype = STANDARD;
  446.                 continue;
  447.             }
  448.             /* start of an alternate-form comment? */
  449.             if (acmptr != NIL
  450.                 && (strptr == NIL || acmptr < strptr)
  451.                 && (chrptr == NIL || acmptr < chrptr)
  452.                 && (blksptr == NIL || acmptr < blksptr)
  453.                 && (blkeptr == NIL || acmptr < blkeptr)) {
  454.                 putKcp (s, acmptr - 1, FALSE);
  455.                 printf ("\\C{}");
  456.                 s = acmendptr;
  457.                 putKcp (acmptr, acmendptr - 1, FALSE);
  458.                 incomm = TRUE;
  459.                 comtype = ALTERNATE;
  460.                 continue;
  461.             }
  462.             /* start of a string? */
  463.             if (strptr != NIL
  464.                 && (chrptr == NIL || strptr < chrptr)
  465.                 && (blksptr == NIL || strptr < blksptr)
  466.                 && (blkeptr == NIL || strptr < blkeptr)) {
  467.                 putKcp (s, strptr - 1, FALSE);
  468.                 printf ("\\S{}");
  469.                 s = strendptr;
  470.                 putKcp (strptr, strendptr - 1, FALSE);
  471.                 instr = TRUE;
  472.                 continue;
  473.             }
  474.             /* start of a character string? */
  475.             if (chrptr != NIL
  476.                 && (blksptr == NIL || chrptr < blksptr)
  477.                 && (blkeptr == NIL || chrptr < blkeptr)) {
  478.                 putKcp (s, chrptr - 1, FALSE);
  479.                 printf ("\\S{}");
  480.                 s = chrendptr;
  481.                 putKcp (chrptr, chrendptr - 1, FALSE);
  482.                 inchr = TRUE;
  483.                 continue;
  484.             }
  485.             /* end of a lexical block */
  486.             if (blkeptr != NIL) {
  487.                 if (blksptr == NIL || blkeptr < blksptr) {
  488.                     putKcp (s, blkeendptr - 1, FALSE);
  489.                     s = blkeendptr;
  490.                     blklevel--;
  491.                     if (psptr >= 0 &&
  492.                         plstack[psptr] >= blklevel) {
  493.  
  494.                         /* end of current procedure */
  495.                         blklevel = plstack[psptr];
  496.  
  497.                         /*
  498.                          * see if we should print the
  499.                          * last proc name
  500.                          */
  501.                         if (--psptr >= 0)
  502.                             prccont = TRUE;
  503.                         else
  504.                             psptr = -1;
  505.                     }
  506.                     continue;
  507.                 }
  508.             }
  509.             /* start of a lexical block */
  510.             if (blksptr != NIL) {
  511.                 putKcp (s, blksendptr - 1, FALSE);
  512.                 s = blksendptr;
  513.                 blklevel++;
  514.                 continue;
  515.             }
  516.             /* check for end of comment */
  517.         } else if (incomm) {
  518.             if ((comendptr = expmatch (s,
  519.                   comtype == STANDARD ? l_comend : l_acmend,
  520.                            NIL, NIL)) != NIL) {
  521.                 putKcp (s, comendptr - 1, TRUE);
  522.                 s = comendptr;
  523.                 incomm = FALSE;
  524.                 printf ("\\CE{}");
  525.             } else {
  526.                 comptr = s;
  527.                 s += strlen (s);
  528.                 putKcp (comptr, s - 1, TRUE);
  529.             }
  530.             continue;
  531.  
  532.             /* check for end of string */
  533.         } else if (instr) {
  534.             if ((strendptr = expmatch (s, l_strend, NIL, NIL))
  535.                  != NIL) {
  536.                 putKcp (s, strendptr - 1, TRUE);
  537.                 s = strendptr;
  538.                 instr = FALSE;
  539.                 printf ("\\SE{}");
  540.             } else {
  541.                 strptr = s;
  542.                 s += strlen (s);
  543.                 putKcp (strptr, s - 1, TRUE);
  544.             }
  545.             continue;
  546.  
  547.         /* check for end of character string */
  548.         } else if (inchr) {
  549.             if ((chrendptr = expmatch (s, l_chrend, NIL, NIL)) != NIL) {
  550.                 putKcp (s, chrendptr - 1, TRUE);
  551.                 s = chrendptr;
  552.                 inchr = FALSE;
  553.                 printf ("\\SE{}");
  554.             } else {
  555.                 chrptr = s;
  556.                 s += strlen (s);
  557.                 putKcp (chrptr, s - 1, TRUE);
  558.             }
  559.             continue;
  560.         }
  561.         /* print out the line */
  562.         chrptr = s;
  563.         s += strlen (s);
  564.         putKcp (chrptr, s - 1, FALSE);
  565.  
  566.     } while (*s);
  567. }
  568.  
  569. void putKcp (char *start, char *end, boolean nix)
  570. /*    register char *start;     start of string to write */
  571. /*    register char *end;      end of string to write */
  572. /*    register boolean nix;    true if we should force nokeyw */
  573. {
  574.     register int i, c;
  575.  
  576.     if (nokeyw)
  577.         nix = TRUE;
  578.  
  579.     while (start <= end) {
  580.         c = *start++;
  581.         /* take care of nice tab stops */
  582.         if (c == '\t') {
  583.             while (start <= end && *start == '\t')
  584.                 start++;
  585.             tabto (width (_start, start));
  586.             continue;
  587.         }
  588.         if (!nix && isIDchr(c)) {
  589.             /* potential keyword */
  590.             start--;
  591.             if (start == _start || !isIDchr(start[-1])) {
  592.                 i = iskw (start);
  593.                 if (i > 0) {
  594.                     printf ("\\K{");
  595.                     while (--i >= 0) {
  596.                         c = *start++;
  597.                         outchar (c);
  598.                     }
  599.                     putchar ('}');
  600.                     continue;
  601.                 }
  602.             }
  603.             start++;
  604.         }
  605.         outchar (c);
  606.     }
  607. }
  608.  
  609.  
  610. int width (char *s, char *os)
  611. {
  612.     register int i = 0, c;
  613.  
  614.     while (s < os) {
  615.         c = *s++;
  616.         if (c == '\t') {
  617.             i = (i + 8) & ~7;
  618.             continue;
  619.         }
  620.         if (c < ' ')
  621.             i += 2;
  622.         else
  623.             i++;
  624.     }
  625.     return (i);
  626. }
  627.  
  628. /* output a string, escaping special characters */
  629. void putstr (char *cp)
  630. {
  631.     register int c;
  632.  
  633.     if (cp == NULL)
  634.         return;
  635.     while ((c = *cp++) != 0)
  636.         outchar (c);
  637. }
  638.  
  639. /*
  640.  * look for a process beginning on this line
  641.  */
  642. boolean isproc (char *s)
  643. {
  644.     /* was: pname[0] = NULL; */
  645.     pname[0] = '\0';
  646.     if ((!l_toplex || blklevel == 0)
  647.         && expmatch (s, l_prcbeg, NIL, pname) != NIL)
  648.         return (TRUE);
  649.     return (FALSE);
  650. }
  651.  
  652.  
  653. /*
  654.  * iskw - check to see if the next word is a keyword
  655.  */
  656. int iskw (char *s)
  657. {
  658.     register char **ss = l_keywds;
  659.     register int i = 1;
  660.     register char *cp = s;
  661.     register int firstc = *s;
  662.  
  663.     while (++cp, isIDchr(*cp))
  664.         i++;
  665.     while (cp = *ss++) {
  666.         if (!l_onecase && firstc != *cp)
  667.             continue;
  668.         if ((*re_strncmp) (s, cp, i) == 0 && !isIDchr(cp[i]))
  669.             return (i);
  670.     }
  671.     return (0);
  672. }
  673.